package ace.cmp.openfeign.core;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.FeignClientBuilder;
import org.springframework.cloud.openfeign.FeignClientFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;

/**
 * @author caspar
 * @date 2023/3/28 10:24
 */
public class AceFeignClientBuilder extends FeignClientBuilder {

  private final ApplicationContext applicationContext;

  public AceFeignClientBuilder(ApplicationContext applicationContext) {
    super(applicationContext);
    this.applicationContext = applicationContext;
  }

  @Override
  public <T> Builder<T> forType(final Class<T> type, final String name) {
    Builder<T> builder = super.forType(type, name);
    setBuilderUrlAndPath(type, name, builder);
    return builder;
  }

  @Override
  public <T> Builder<T> forType(
      final Class<T> type, final FeignClientFactoryBean clientFactoryBean, final String name) {
    Builder<T> builder = super.forType(type, clientFactoryBean, name);
    setBuilderUrlAndPath(type, name, builder);
    return builder;
  }

  private <T> void setBuilderUrlAndPath(Class<T> type, String name, Builder builder) {
    FeignClient feignClientAnn = AnnotationUtils.findAnnotation(type, FeignClient.class);
    String realName = AceFeignClientsRegistrar.getName(name);
    String url = this.getUrlFromAnnotationOrEnvironment(realName, feignClientAnn);
    String path = this.getPathFromAnnotationOrEnvironment(realName, feignClientAnn);
    if (url != null && url.length() != 0) {
      builder.url(url);
    }
    if (path != null && path.length() != 0) {
      builder.path(path);
    }
  }

  private <T> String getPathFromAnnotationOrEnvironment(
      String realName, FeignClient feignClientAnn) {
    if (feignClientAnn == null) {
      return "";
    }
    String path = "";
    if (feignClientAnn.path() != null && feignClientAnn.path().length() > 0) {
      path = applicationContext.getEnvironment().resolvePlaceholders(feignClientAnn.path());
    }
    if (path == null || path.length() == 0) {
      String pathVarName =
          String.format("${spring.cloud.openfeign.client.config.%s.path:}", realName);
      path = applicationContext.getEnvironment().resolvePlaceholders(pathVarName);
    }
    return path;
  }

  private <T> String getUrlFromAnnotationOrEnvironment(
      String realName, FeignClient feignClientAnn) {
    if (feignClientAnn == null) {
      return "";
    }
    String url = "";
    if (feignClientAnn.url() != null && feignClientAnn.url().length() > 0) {
      url = applicationContext.getEnvironment().resolvePlaceholders(feignClientAnn.url());
    }
    if (url == null || url.length() == 0) {
      String urlVarName =
          String.format("${spring.cloud.openfeign.client.config.%s.url:}", realName);
      url = applicationContext.getEnvironment().resolvePlaceholders(urlVarName);
    }
    return url;
  }
}
